/*
 * 
 * Copyright 2011 visual-analysis-of-cancer.
 * This file is part of visual-analysis-of-cancer.
 * 
 * visual-analysis-of-cancer is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * visual-analysis-of-cancer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with kOSMik.  If not, see <http://www.gnu.org/licenses/>.
 *  
 * visual-analysis-of-cancer:
 * An tool to analye the WHO and GLOBOCAN cancer data.
 * http://code.google.com/p/visual-analysis-of-cancer/
 * 
 * 
 * 
 * Authors: Erik Sniegula, Johannes Dahlke
 * 
 * Module:  Programming in Processing for Visual Analytics
 * Group:   20
 * 
 * Created: Aug. 2011
 * Version: 1.0
 *
 */
 




package de.fuberlin.processing.who.cancer.controlp5ex;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.ListResourceBundle;
import java.util.Vector;
import controlP5.Button;
import controlP5.CColor;
import controlP5.ControlEvent;
import controlP5.ControlP5;
import controlP5.ControlP5Constants;
import controlP5.ControllerGroup;
import controlP5.ControllerInterface;
import controlP5.ListBox;
import controlP5.ListBoxItem;
import controlP5.Slider;
import de.fuberlin.processing.who.cancer.utils.Graphics;
import de.fuberlin.processing.who.cancer.utils.Test;


public class MultiSelectListBox extends ListBox {

	private HashMap<String, ListBoxItem> itemsByName = new HashMap<String, ListBoxItem>();
	private Vector<ListBoxItem> selectedItems = new Vector<ListBoxItem>();


	public MultiSelectListBox( ControlP5 theControlP5, ControllerGroup theGroup,
			String theName, int theX, int theY, int theW, int theH) {
		super( theControlP5, theGroup, theName, theX, theY, theW, theH);
		this._myScrollbar.setSliderMode( Slider.FLEXIBLE);
		toUpperCase( false);
	}


	@Override
	public void controlEvent( ControlEvent theEvent) {
		if ( theEvent.getController() instanceof Button) {
			ListBoxItem clickedItem = itemsByName.get( theEvent.getLabel());
			if ( isItemSelected( clickedItem)) {
				// remove
				unselectItem( clickedItem);
			} else {
				// insert
				selectItem( clickedItem);
			}
			ControlEvent myEvent = new ControlEvent( this);
			controlP5.controlbroadcaster().broadcast( myEvent,
					ControlP5Constants.FLOAT);
		} else
			super.controlEvent( theEvent);
	}


	private void unselectItem( ListBoxItem item) {
		if ( selectedItems.contains( item)) {
			// remove
			selectedItems.remove( item);
			item.setColorBackground( this.getColor().getBackground());
			item.setColorLabel( this.getColor().getCaptionLabel());
			int index = items.indexOf( item);
			// get the item presenting button and force color changing
			// induce repaint
			updateListBoxItems();
		}
	}


	private void selectItem( ListBoxItem item) {
		if ( !selectedItems.contains( item)) {
			// add
			selectedItems.add( item);
			item.setColorBackground( Graphics.getColorNuance( this.getColor()
					.getBackground(), 170));
			item.setColorLabel( Graphics.getColorNuance( this.getColor()
					.getBackground(), -20));
			int index = items.indexOf( item);
			// induce repaint
			updateListBoxItems();
		}
	}


	private boolean isItemSelected( ListBoxItem item) {
		return selectedItems.contains( item);
	}


	/**
	 * cut text that need more place then the button has
	 */
	private String shrinkText( String theText) {
		String shrinkedText = theText;
		float textWidth = controlP5.papplet.textWidth( shrinkedText);
		while ( textWidth > this.getWidth() && textWidth > 0) {
			shrinkedText = shrinkedText.substring( 0, shrinkedText.length() - 1);
			textWidth = ControlP5.papplet.textWidth( shrinkedText);
		}
		return shrinkedText;
	}


	@Override
	public ListBoxItem addItem( String theName, int theValue) {
		String itemName = shrinkText( theName);
		ListBoxItem listBoxItem = super.addItem( itemName, theValue);
		itemsByName.put( itemName, listBoxItem);
		// kein uppercase
		for ( Button button : buttons) {
			button.getCaptionLabel().toUpperCase( false);
		}
		return listBoxItem;
	}


	@Override
	public void removeItem( String arg0) {
		items.remove( arg0);
		super.removeItem( arg0);
	}


	public Collection<Integer> getSelectedValues() {
		Vector<Integer> selectedValues = new Vector<Integer>();
		for ( ListBoxItem item : selectedItems) {
			selectedValues.add( item.getValue());
		}
		return selectedValues;
	}


	public void clearSelection() {
		Vector<ListBoxItem> copyOfSelectedItems = new Vector<ListBoxItem>();
		copyOfSelectedItems.addAll( selectedItems);
		for ( ListBoxItem item : copyOfSelectedItems) {
			unselectItem( item);
		}
	}


	public void setSelectedValues( Collection<Integer> values) {
		clearSelection();
		if ( Test.isAssigned( values)) {
			for ( Integer value : values) {
				for ( ListBoxItem item : items) {
					if ( item.getValue() == value)
						selectItem( item);
				}
			}
		}
	}


	public void setSelectedValuesByLabel( Collection<String> valueLabels) {
		clearSelection();
		if ( Test.isAssigned( valueLabels)) {
			for ( String label : valueLabels) {
				selectItem( itemsByName.get( label));
			}
		}
	}

}